package main

import "fmt"

func main() {

	// 函数传参
	testFunc()

	// 值传递和引用传递
	testValueAndRefSend()

	// 延迟函数
	testDefFunc()

	// 匿名函数
	testAnonymousFunc()

	// 回调函数
	testCallBackFunc()

	// 闭包
	testClosure()
}

func testClosure() {
	/*
		闭包：一个外层函数中有内层函数，该内层函数中，会操作外层函数的局部变量，并且该外层函数的返回值就是这个内层函数。这个内层函数和外层函数的局部变量，统称为闭包结构。
		局部变量的生命周期会发生改变，正常的局部变量会随着函数的调用而创建，随着函数的结束而销毁。但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁，因为内层函数还在继续使用
	*/
	r1 := increment()
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())

	rr2 := increment()
	fmt.Println(r1())
	fmt.Println(rr2())
	fmt.Println(r1())
}

func testCallBackFunc() {
	r2 := oper(3, 4, add)
	fmt.Println("r2", r2)
	r3 := oper(8, 4, func(a, b int) int {
		if b == 0 {
			fmt.Println("除数不能为0")
			return 0
		}
		return a / b
	})
	fmt.Println("r3", r3)

	fmt.Println("\n-------")
}

func testAnonymousFunc() {
	// 匿名函数
	fun3 := func() {
		fmt.Println("我是匿名函数")
	}
	fun3()
	// 简化写法
	func() {
		fmt.Println("我是匿名函数")
	}()
	// 加入参出参
	rr1 := func(a, b int) int {
		return a + b
	}(1, 2)
	fmt.Println("匿名", rr1)

	fmt.Println("\n-------")
}

func testDefFunc() {
	/*
		defer: 一个函数的执行被延迟了
			(1) 你可以在函数中添加多个defer语句，当函数执行到最后时，这些defer语句会按照逆序执行，最后该函数返回，特别是当你在进行一些打开资源的操作时，遇到错误需要提前返回，在返回前你需要关闭相应的资源，不然很容易造成资源泄露等问题
		    (2) 如果有很多调用defer，namedefer是采用后进先出(栈)模式
	*/
	aa := 10
	fmt.Println("aa=", aa)
	defer deferFunc(aa)
	aa++
	fmt.Println("aa=", aa)

	fmt.Println("\n-------")
}

func testValueAndRefSend() {
	/*
		值传递：传递的是数据的副本，修改数据对于原始的数据没有影响
		值类型的数据，默认都是值传递：基础类型、array、struct
	*/
	arr := [4]int{1, 2, 3, 4}
	// 这是拷贝传递！
	update(arr)
	fmt.Println("arr调用后", arr)

	fmt.Println("\n-------")

	/*
		引用传递：传入的是地址
		引用类型的数据：slice、map、channel
	*/
	// 切片：可以扩容的数组
	s1 := []int{1, 2, 3, 4}
	update2(s1)
	fmt.Println("s1调用后", s1)

	fmt.Println("\n-------")
}

func testFunc() {
	// 函数
	ans1 := add(10, 20)
	fmt.Println("ans1", ans1)

	fmt.Println("\n--------------")

	x, y := swap("aa", "bb")
	fmt.Println(x, y)

	fmt.Println("\n--------------")

	getSum("sum", 1, 2, 3)

	fmt.Println("\n-------")
}

func increment() func() int {
	i := 0
	fun := func() int {
		i++
		return i
	}
	return fun
}

func oper(a, b int, fun func(int, int) int) int {
	r := fun(a, b)
	return r
}

func add(a, b int) int {
	c := a + b
	return c
}

// 有多个返回值的函数
func swap(x, y string) (string, string) {
	return y, x
}

// ... 可变参数
func getSum(ms string, nums ...int) {
	sum := 0
	for i := range nums {
		fmt.Println(nums[i])
		sum += nums[i]
	}
	fmt.Println(ms, sum)
}

func update(arr [4]int) {
	fmt.Println("arr接收", arr)
	arr[0] = 100
	fmt.Println("arr修改", arr)
}

func update2(s2 []int) {
	fmt.Println("arr接收", s2)
	s2[0] = 100
	fmt.Println("arr修改", s2)
}

func deferFunc(a int) {
	fmt.Println("函数里面的a--", a)
}
